package com.gitee.wsl.flow.combine

import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

fun <T> Flow<T>.wrap(): CFlow<T> = CFlow(this)

class CFlow<T>(private val origin: Flow<T>) : Flow<T> by origin {
    fun watch(block: (T) -> Unit): AutoCloseable {
        val job = Job( /*ConferenceService.coroutineContext[Job]*/ )

        onEach {
            block(it)
        }.launchIn(CoroutineScope(SupervisorJob() + Dispatchers.Main))

        return AutoCloseable { job.cancel() }
    }
}


@Composable
fun <T> CFlow<T>.observeAsState(initial: T? = null): State<T?> {
    val state = remember { mutableStateOf(initial) }
    val flow = this
    DisposableEffect(this) {
        val observer = flow.watch { state.value = it }
        onDispose {
            observer.close()
        }
    }

    return state
}

@Composable
fun <T, R> CFlow<T>.launchAsState(key: R?, initial: T): T {
    var navigation by remember(key) { mutableStateOf(initial) }
    var observer: AutoCloseable? = null
    val flow = this

    LaunchedEffect(key) {
        observer = flow.watch {
            it?.let {
                navigation = it
            }
        }
    }

    DisposableEffect(key) {
        onDispose {
            observer?.close()
        }
    }

    return navigation
}